package net.entelijan.cobean.bind;

import net.entelijan.cobean.core.IRemovable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Abstract ModelChangeListener for components.
 * 
 * @param <C> The class of the component
 * @param <T> The class of the value that is beeing displayed. Actually the
 *            class of the model entries that can be bound to that component
 *            later.
 */
public abstract class AbstractModelChangeListener<T, C> implements IModelChangeListener, IRemovable {

    private static Log log = LogFactory.getLog(AbstractModelChangeListener.class);

    protected C component;

    protected IBeanProperty beanProperty;

    private IRemovableFactory removableFactory;

    public AbstractModelChangeListener(IBeanProperty beanProperty, C component,
            IRemovableFactory removableFactory) {
        super();
        this.beanProperty = beanProperty;
        this.component = component;
        this.removableFactory = removableFactory;
    }

    @SuppressWarnings("unchecked")
    protected T convertToModelType(Object value) {
        log.debug("[" + getClass().getName() + "#convertToString] " + value);
        return (T) value;
    }

    public void setComponent(C comp) {
        this.component = comp;
    }

    public void updateComponent() {
        T value;
        value = convertToModelType(this.beanProperty.getValue());
        if (this.component != null) {
            log.debug("[" + getClass().getName() + "#updateComponentInternal] component='"
                    + component + "' with value:'" + value + "'");
            setComponentValue(value);
        }
    }

    public abstract void setComponentValue(T value);

    public void setModelValue(Object obj) {
        this.beanProperty.setValue(obj);
    }

    @Override
    public void remove() {
        log.debug("[remove] removableFactory='" + removableFactory + "'");
        if (this.removableFactory != null) {
            this.removableFactory.createRemovable().remove();
        }
    }

    @Override
    public void prepareComponent(Object oldVal, Object newVal) {
        // In common cases nothing has to be done
    }

    @Override
    public String getPropertyName() {
        return this.beanProperty.getPropertyName();
    }

}
